package config

import (
	"time"

	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
)

type Reader interface {
	AddFiles(files ...string) error
	OnChange(fn func(e fsnotify.Event))
	Viper() *viper.Viper
	AllSettings() map[string]any
	// Has 判断配置key是否存在
	Has(key string) bool
	// GetE 读取指定key配置, 返回 val<any> 和 key是否存在的状态
	GetE(key string) (val any, exists bool)

	GetString(key string) string
	GetStringD(key string, defaultVal string) string
	GetStringE(key string) (string, error)

	GetInt(key string) int
	GetIntD(key string, defaultVal int) int
	GetIntE(key string) (int, error)

	GetInt8(key string) int8
	GetInt8D(key string, defaultVal int8) int8
	GetInt8E(key string) (int8, error)

	// GetInt16 读取并转换目标为 int32, 读取或转换失败则返回零值
	GetInt16(key string) int16
	// GetInt16D 读取并转换目标为 int32, 读取或转换失败则返回 defaultVal 指定的默认值
	GetInt16D(key string, defaultVal int16) int16
	// GetInt16E 读取并转换目标为 int32, 读取或转换失败则返零值和错误信息
	GetInt16E(key string) (int16, error)

	// GetInt32 读取并转换目标为 int32, 读取或转换失败则返回零值
	GetInt32(key string) int32
	// GetInt32D 读取并转换目标为 int32, 读取或转换失败则返回 defaultVal 指定的默认值
	GetInt32D(key string, defaultVal int32) int32
	// GetInt32E 读取并转换目标为 int32, 读取或转换失败则返零值和错误信息
	GetInt32E(key string) (int32, error)

	// GetInt64 读取并转换目标为 int64, 读取或转换失败则返回零值
	GetInt64(key string) int64
	// GetInt64D 读取并转换目标为 int64, 读取或转换失败则返回 defaultVal 指定的默认值
	GetInt64D(key string, defaultVal int64) int64
	// GetInt64E 读取并转换目标为 int64, 读取或转换失败则返零值和错误信息
	GetInt64E(key string) (int64, error)

	// GetUint 读取并转换目标为 uint, 读取或转换失败则返回零值
	GetUint(key string) uint
	// GetUintD 读取并转换目标为 uint, 读取或转换失败则返回 defaultVal 指定的默认值
	GetUintD(key string, defaultVal uint) uint
	// GetUintE 读取并转换目标为 uint, 读取或转换失败则返零值和错误信息
	GetUintE(key string) (uint, error)

	// GetUint8 读取并转换目标为 uint8, 读取或转换失败则返回零值
	GetUint8(key string) uint8
	// GetUint8D 读取并转换目标为 uint8, 读取或转换失败则返回 defaultVal 指定的默认值
	GetUint8D(key string, defaultVal uint8) uint8
	// GetUint8E 读取并转换目标为 uint8, 读取或转换失败则返零值和错误信息
	GetUint8E(key string) (uint8, error)

	// GetUint16 读取并转换目标为 uint16, 读取或转换失败则返回零值
	GetUint16(key string) uint16
	// GetUint16D 读取并转换目标为 uint16, 读取或转换失败则返回 defaultVal 指定的默认值
	GetUint16D(key string, defaultVal uint16) uint16
	// GetUint16E 读取并转换目标为 uint16, 读取或转换失败则返零值和错误信息
	GetUint16E(key string) (uint16, error)

	// GetUint32 读取并转换目标为 uint32, 读取或转换失败则返回零值
	GetUint32(key string) uint32
	// GetUint32D 读取并转换目标为 uint32, 读取或转换失败则返回 defaultVal 指定的默认值
	GetUint32D(key string, defaultVal uint32) uint32
	// GetUint32E 读取并转换目标为 uint32, 读取或转换失败则返零值和错误信息
	GetUint32E(key string) (uint32, error)

	// GetUint64 读取并转换目标为 uint64, 读取或转换失败则返回零值
	GetUint64(key string) uint64
	// GetUint64D 读取并转换目标为 uint64, 读取或转换失败则返回 defaultVal 指定的默认值
	GetUint64D(key string, defaultVal uint64) uint64
	// GetUint64E 读取并转换目标为 uint64, 读取或转换失败则返零值和错误信息
	GetUint64E(key string) (uint64, error)

	// GetFloat32 读取并转换目标为 float32, 读取或转换失败则返回零值
	GetFloat32(key string) float32
	// GetFloat32D 读取并转换目标为 float32, 读取或转换失败则返回 defaultVal 指定的默认值
	GetFloat32D(key string, defaultVal float32) float32
	// GetFloat32E 读取并转换目标为 float32, 转换失败则返零值和错误信息
	GetFloat32E(key string) (float32, error)

	// GetFloat64 读取并转换目标为 float64, 读取或转换失败则返回零值
	GetFloat64(key string) float64
	// GetFloat64D 读取并转换目标为 float64, 读取或转换失败则返回 defaultVal 指定的默认值
	GetFloat64D(key string, defaultVal float64) float64
	// GetFloat64E 读取并转换目标为 float64, 读取或转换失败则返零值和错误信息
	GetFloat64E(key string) (float64, error)

	// GetBool 读取并转换目标为 bool, 读取或转换失败则返回零值
	GetBool(key string) bool
	// GetBoolD 读取并转换目标为 bool, 读取或转换失败则返回 defaultVal指定的 bool
	GetBoolD(key string, defaultVal bool) bool
	// GetBoolE 读取并转换目标为 bool, 读取或转换失败则返零值和错误信息
	GetBoolE(key string) (bool, error)

	// GetTime 读取并转换目标为time.Time
	//   - 如待转换目标是字符串(日期时间)未包含时区信息时，则使用 Server/Local 时区区
	GetTime(key string) time.Time
	// GetTimeD  读取并转换目标为time.Time, 读取或转换失败则返回defaultVal指定的默认值
	//   - 如待转换目标是数值(当做Unix秒级时间戳), 则使用 Server/Local 时区
	//   - 如待转换目标是字符串(日期时间)未包含时区信息时, 则使用 Server/Local 时区
	GetTimeD(key string, defaultVal time.Time) time.Time
	// GetTimeE  读取并转换目标为time.Time, 读取或转换失败则返回空Time对象和错误信息
	//   - 如待转换目标是数值(当做Unix秒级时间戳), 则使用 Server/Local 时区
	//   - 如待转换目标是字符串(日期时间)未包含时区信息时, 则使用 Server/Local 时区
	GetTimeE(key string) (time.Time, error)
	// GetTimeWith 读取并转换目标为指定的时区的time.Time(指定时区), 读取或转换失败则返回空Time对象和错误信息
	//   - 如待转换目标是数值(当做Unix秒级时间戳), 则使用 location 指定的时区
	//   - 如待转换目标是字符串(日期时间)未包含时区信息时, 则使用 location 指定的时区
	GetTimeWith(key string, location *time.Location) (time.Time, error)

	// GetTimeDuration 读取并转换目标为time.Duration, 读取或转换失败则返回零值的Duration
	GetTimeDuration(key string) time.Duration
	// GetTimeDurationD 读取并转换目标为time.Duration, 读取或转换失败则返回defaultVal指定的默认值
	GetTimeDurationD(key string, defaultVal time.Duration) time.Duration
	// GetTimeDurationE 读取并转换目标为time.Duration, 读取或转换失败则返回零值的Duration和错误信息
	GetTimeDurationE(key string) (time.Duration, error)

	// GetTimeMonth 读取并转换目标为time.Month, 读取或转换失败则返回零值的Month
	GetTimeMonth(key string) time.Month
	// GetTimeMonthD 读取并转换目标为time.Month, 读取或转换失败则返回defaultVal指定的Month对象
	GetTimeMonthD(key string, defaultVal time.Month) time.Month
	// GetTimeMonthE 读取并转换目标为time.Month, 读取或转换失败则返回零值的Month和错误信息
	GetTimeMonthE(key string) (time.Month, error)

	// GetTimeWeekday 读取并转换目标为time.Weekday, 读取或转换失败则返回零值的Weekday
	GetTimeWeekday(key string) time.Weekday
	// GetTimeWeekdayD 读取并转换目标为time.Weekday, 读取或转换失败则返回defaultVal指定的默认值
	GetTimeWeekdayD(key string, defaultVal time.Weekday) time.Weekday
	// GetTimeWeekdayE 读取并转换目标为time.Weekday, 读取或转换失败则返回零值的Weekday和错误信息
	GetTimeWeekdayE(key string) (toVal time.Weekday, err error)

	// Slice Values
	SliceAny(key string) []any
	SliceAnyD(key string, defaultVal []any) []any
	SliceString(key string) []string
	SliceStringD(key string, defaultVal []string) []string
	SliceInt(key string) []int
	SliceIntD(key string, defaultVal []int) []int
	SliceInt64(key string) []int64
	SliceInt64D(key string, defaultVal []int64) []int64
	SliceUint(key string) []uint
	SliceUintD(key string, defaultVal []uint) []uint
	SliceUint64(key string) []uint64
	SliceUint64D(key string, defaultVal []uint64) []uint64
	SliceFloat32(key string) []float32
	SliceFloat32D(key string, defaultVal []float32) []float32
	SliceFloat64(key string) []float64
	SliceFloat64D(key string, defaultVal []float64) []float64
	SliceBool(key string) []bool
	SliceBoolD(key string, defaultVal []bool) []bool
	// SliceTime 获取参数为时间对象切片，如待转换参数值为日期时间字符串，则使用本地时区
	SliceTime(key string) []time.Time
	SliceTimeD(key string, defaultVal []time.Time) []time.Time
	SliceTimeDuration(key string) []time.Duration
	SliceTimeDurationD(key string, defaultVal []time.Duration) []time.Duration
	// SliceMapAny 获取参数为map[string]any切片
	//   - 注意: Viper 统一将 map => key 已经被转换为小写
	//   - 所以获取到的 map => key 已经被转换为小写
	//   - 注意: 获取到的整数值为int64,浮点数为float64
	SliceMapAny(key string) []map[string]any
	SliceMapAnyD(key string, defaultVal []map[string]any) []map[string]any
	// SliceMapString 获取参数为map[string]string切片
	//   - 注意: Viper 统一将 map => key 已经被转换为小写
	//   - 所以获取到的 map => key 已经被转换为小写
	SliceMapString(key string) []map[string]string
	SliceMapStringD(key string, defaultVal []map[string]string) []map[string]string
	SliceMapStringE(key string) ([]map[string]string, error)
	// Map Values
	// MapAny 获取参数为map[string]any
	//   - 注意: Viper 统一将 map => key 已经被转换为小写
	//   - 所以获取到的 map => key 已经被转换为小写
	//   - 注意: 获取到的整数值为int64,浮点数为float64
	MapAny(key string) map[string]any
	MapAnyD(key string, defaultVal map[string]any) map[string]any
	// MapString 获取参数为map[string]string
	//   - 注意: Viper 统一将 map => key 已经被转换为小写
	//   - 所以获取到的 map => key 已经被转换为小写
	MapString(key string) map[string]string
	MapStringD(key string, defaultVal map[string]string) map[string]string
	// MapStringSlice 获取参数为map[string][]string
	//   - 注意: Viper 统一将 map => key 已经被转换为小写
	//   - 所以获取到的 map => key 已经被转换为小写
	MapStringSlice(key string) map[string][]string
	MapStringSliceD(key string, defaultVal map[string][]string) map[string][]string
	MapInt(key string) map[string]int
	MapIntD(key string, defaultVal map[string]int) map[string]int
	MapInt64(key string) map[string]int64
	MapInt64D(key string, defaultVal map[string]int64) map[string]int64
	MapUint(key string) map[string]uint
	MapUintD(key string, defaultVal map[string]uint) map[string]uint
	MapUint64(key string) map[string]uint64
	MapUint64D(key string, defaultVal map[string]uint64) map[string]uint64
	MapFloat32(key string) map[string]float32
	MapFloat32D(key string, defaultVal map[string]float32) map[string]float32
	MapFloat64(key string) map[string]float64
	MapFloat64D(key string, defaultVal map[string]float64) map[string]float64
	MapBool(key string) map[string]bool
	MapBoolD(key string, defaultVal map[string]bool) map[string]bool
	// MapTime 获取参数为时间Map，如待转换参数值为日期时间字符串，则使用本地时区
	MapTime(key string) map[string]time.Time
	MapTimeD(key string, defaultVal map[string]time.Time) map[string]time.Time
	MapTimeDuration(key string) map[string]time.Duration
	MapTimeDurationD(key string, defaultVal map[string]time.Duration) map[string]time.Duration

	ScanTo(refVal any) error              // like Viper.Unmarshal
	ScanKey(key string, refVal any) error // like Viper.UnmarshalKey
}
